package com.insight.modules.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import com.insight.modules.system.entity.SysCheckRule;
import com.insight.modules.system.mapper.SysCheckRuleMapper;
import com.insight.modules.system.service.ISysCheckRuleService;
import org.springframework.stereotype.Service;

import java.util.regex.Pattern;

/**
 * @Description: 编码校验规则
 * @Author: jeecg-boot
 * @Date: 2020-02-04
 * @Version: V1.0
 */
@Service
public class SysCheckRuleServiceImpl extends ServiceImpl<SysCheckRuleMapper, SysCheckRule> implements ISysCheckRuleService {

    /**
     * 特殊符号 "*" 表示校验整个值，不分段截取
     */
    private final String CHECK_ALL_SYMBOL = "*";

    /**
     * 根据规则编码查询对应的校验规则实体
     */
    @Override
    public SysCheckRule getByCode(String ruleCode) {
        LambdaQueryWrapper<SysCheckRule> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysCheckRule::getRuleCode, ruleCode);
        return super.getOne(queryWrapper);
    }

    /**
     * 根据用户设定的自定义校验规则对传入的值进行校验
     * 规则以 JSON 数组格式存储在 ruleJson 字段，每条规则包含：
     *  - digits: 校验长度或特殊符号 "*" 表示整串校验
     *  - pattern: 正则表达式
     *  - message: 校验失败时提示信息
     *
     * @param checkRule 规则实体
     * @param value 待校验的字符串
     * @return 返回 JSONObject，null表示校验通过，否则返回失败信息和校验相关字段
     */
    @Override
    public JSONObject checkValue(SysCheckRule checkRule, String value) {
        if (checkRule != null && StringUtils.isNotBlank(value)) {
            String ruleJson = checkRule.getRuleJson();
            if (StringUtils.isNotBlank(ruleJson)) {
                int beginIndex = 0; // 校验字符串截取起始位置
                JSONArray rules = JSON.parseArray(ruleJson);
                for (int i = 0; i < rules.size(); i++) {
                    JSONObject result = new JSONObject();
                    JSONObject rule = rules.getJSONObject(i);

                    // 规则字段
                    String digits = rule.getString("digits");    // 校验位数或 "*"
                    String pattern = rule.getString("pattern");  // 正则表达式
                    String message = rule.getString("message");  // 校验失败提示

                    // 结果包装
                    result.put("digits", digits);
                    result.put("pattern", pattern);
                    result.put("message", message);

                    String checkValue;

                    // 如果 digits 为 "*"，校验整个字符串
                    if (CHECK_ALL_SYMBOL.equals(digits)) {
                        checkValue = value;
                    } else {
                        // 截取字符串的特定位数部分进行校验
                        int num = Integer.parseInt(digits);
                        int endIndex = beginIndex + num;
                        // 防止截取越界
                        endIndex = Math.min(endIndex, value.length());
                        // 如果截取开始位置大于结束位置（用户输入还不够长），赋空字符串
                        if (beginIndex > endIndex) {
                            checkValue = "";
                        } else {
                            checkValue = value.substring(beginIndex, endIndex);
                        }
                        result.put("beginIndex", beginIndex);
                        result.put("endIndex", endIndex);
                        beginIndex += num; // 移动截取起点，适用于后续规则
                    }
                    result.put("checkValue", checkValue);

                    // 正则校验
                    boolean passed = Pattern.matches(pattern, checkValue);
                    result.put("passed", passed);

                    // 校验失败立即返回结果
                    if (!passed) {
                        return result;
                    }
                }
            }
        }
        // 校验通过返回null
        return null;
    }
}

